﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SchemaExplorer;
using Tilver.Coder;
using Tilver.Coder.Utility;

namespace Tilver.Coder.Core
{
    /// <summary>
    /// 数据加载器
    /// </summary>
    public class DataLoader : LoaderBase
    {
        public override void LoadDataBase(CoderDataBase cDataBase)
        {
            if (cDataBase.IsLoad)
            {
                #region 从数据库加载数据

                base.ReportProgress("数据加载开始...");
                Type providerType = null;
                switch (cDataBase.DataProviderType)
                {
                    case DataProviderTypeEnum.MSSQL:
                        providerType = typeof(SchemaExplorer.SqlSchemaProvider);
                        break;
                    case DataProviderTypeEnum.Oracle:
                        providerType = typeof(SchemaExplorer.OracleSchemaProvider);
                        break;
                    case DataProviderTypeEnum.MySQL:
                        providerType = typeof(SchemaExplorer.MySQLSchemaProvider.MySQLSchemaProvider);
                        break;
                    default:
                        throw new NotImplementedException();
                }
                //加载数据库
                var ds = new DataSource("CG", cDataBase.ConnectionString, providerType);
                var dataBaseSchema = ds.CreateInstance();
                cDataBase.Project = this.Project;
                cDataBase.CodeName = dataBaseSchema.Name.ToCoderCodeName();
                cDataBase.Name = dataBaseSchema.Name;

                if (!Worker.CancellationPending)
                {
                    base.ReportProgress("开始加载表...");
                    cDataBase.Tables.Clear();
                    LoadTables(cDataBase, dataBaseSchema);
                    base.ReportProgress("表加载完成");
                }
                if (!Worker.CancellationPending)
                {
                    base.ReportProgress("开始加载视图...");
                    cDataBase.Views.Clear();
                    LoadViews(cDataBase, dataBaseSchema);
                    base.ReportProgress("视图加载完成");
                }
                if (!Worker.CancellationPending)
                {
                    base.ReportProgress("开始加载存储过程...");
                    cDataBase.Commands.Clear();
                    LoadCommands(cDataBase, dataBaseSchema);
                    base.ReportProgress("存储过程加载完成");
                }
                if (!Worker.CancellationPending)
                {
                    base.OnLoadDataBaseCompleted(cDataBase);
                }
                dataBaseSchema = null;
                ds = null;

                #endregion
            }
            else
            {
                #region 从保存文件中加载
                //数据库
                cDataBase.Project = this.Project;
                //表
                foreach ( var coderTable in cDataBase.Tables)
                {
                    coderTable.DataBase = cDataBase;
                    //主键
                    if (coderTable.HasPrimaryKey)
                    {
                        coderTable.PrimaryKey.DataBase = cDataBase;
                        coderTable.PrimaryKey.Table = coderTable;
                    }
                    //外键
                    foreach (var foreignKey in coderTable.ForeignKeys)
                    {
                        foreignKey.DataBase = cDataBase;
                    }
                    //列
                    foreach (var coderColumn in coderTable.Columns)
                    {
                        coderColumn.Table = coderTable;
                    }
                    //索引
                    foreach (var coderIndex in coderTable.Indexes)
                    {
                        coderIndex.Table = coderTable;
                    }
                }
                //视图
                foreach ( var coderView in cDataBase.Views)
                {
                    coderView.DataBase = cDataBase;
                }
                //存储过程
                foreach (var coderCommand in cDataBase.Commands)
                {
                    coderCommand.DataBase = cDataBase;
                }
                #endregion
            }
        }

        #region 加载表

        /// <summary>
        /// 加载表数据
        /// </summary>
        /// <param name="cDataBase"></param>
        /// <param name="dataBase"></param>
        private void LoadTables(CoderDataBase cDataBase, DatabaseSchema dataBase)
        {
            if (Worker.CancellationPending) return;
            //添加表
            if (dataBase.Tables == null || dataBase.Tables.Count <= 0) return;
            foreach (var cTable in dataBase.Tables.Select(appendTable => appendTable.ToCoderTable()))
            {
                cTable.DataBase = cDataBase;
                cDataBase.Tables.Add(cTable);
                ReportProgress(string.Format("表[{0}]加载成功", cTable.FullName));
            }
            
            foreach (var coderTable in cDataBase.Tables)
            {
                //外键
                foreach (var foreignKey in coderTable.ForeignKeys)
                {
                    foreignKey.DataBase = cDataBase;
                }
            }

            ReportProgress(string.Format("共加载表[{0}]个", cDataBase.Tables.Count));
            /*
            var cTableNames = cDataBase.Tables.Select(w => w.FullName).ToList();
            var tableNames = dataBase.Tables.Select(w => w.FullName).ToList();
            var deleteTableNames = cTableNames.Except(tableNames).ToList(); //将要删除的表
            var appendTableNames = tableNames.Except(cTableNames).ToList(); //新增加的表            
            var currentTableNames = cTableNames.Intersect(tableNames).ToList(); //已经存在的表(比较是否修改)
            //删除表
            ReportProgress("开始删除表...");
            foreach (var deleteTableName in deleteTableNames)
            {
                cDataBase.Tables.Remove(cDataBase.Tables.FirstOrDefault(w => w.FullName == deleteTableName));
                ReportProgress(string.Format("表[{0}]删除成功", deleteTableName));
            }
            ReportProgress(string.Format("删除表[{0}]个", deleteTableNames.Count));
            //新增表
            ReportProgress("开始新增表...");
            foreach (var appendTable in dataBase.Tables.Where(w => appendTableNames.Contains(w.FullName)).Select(appendTable => appendTable.ToCoderTable()))
            {
                appendTable.DataBase = cDataBase;
                cDataBase.Tables.Add(appendTable);
                ReportProgress(string.Format("新增表[{0}]", appendTable.FullName));
            }
            ReportProgress(string.Format("新增表[{0}]个", appendTableNames.Count));
            */

        }

        #endregion
        #region 加载视图

        /// <summary>
        /// 加载视图
        /// </summary>
        /// <param name="cDataBase"></param>
        /// <param name="dataBase"></param>
        private void LoadViews(CoderDataBase cDataBase, DatabaseSchema dataBase)
        {
            //添加视图
            if (dataBase.Views == null || dataBase.Views.Count <= 0) return;
            foreach (var cView in dataBase.Views.Select(appendView => appendView.ToCoderView()))
            {
                cView.DataBase = cDataBase;
                cDataBase.Views.Add(cView);
                ReportProgress(string.Format("视图[{0}]加载成功", cView.FullName));
            }
            ReportProgress(string.Format("共加载视图[{0}]个", cDataBase.Views.Count));
        }

        #endregion
        #region 加载存储过程
        /// <summary>
        /// 加载存储过程
        /// </summary>
        /// <param name="cDataBase"></param>
        /// <param name="dataBase"></param>
        private void LoadCommands(CoderDataBase cDataBase, DatabaseSchema dataBase)
        {
            //添加存储过程
            if (dataBase.Commands == null || dataBase.Commands.Count <= 0) return;
            foreach (var cCommand in dataBase.Commands.Select(appendCommand => appendCommand.ToCoderCommand()))
            {
                cCommand.DataBase = cDataBase;
                cDataBase.Commands.Add(cCommand);
                ReportProgress(string.Format("存储过程[{0}]加载成功", cCommand.FullName));
            }
            ReportProgress(string.Format("共加载存储过程[{0}]个", cDataBase.Commands.Count));
        }
        #endregion
    }


}
